using System;
using System.Collections.Generic;
using System.Text;

namespace H2.DataTypes
{
    [Serializable]
    public class Bitmask
    {
        #region Instances
        private bool[] __bits;
        private string[] __names;
        private int __length;
        #endregion

        #region Accessors
        public bool[] Bits { get { return __bits; } set { __bits = value; } }
        public string[] BitNames { get { return __names; } set { __names = value; } }
        public int ByteCountLength { get { return __length; } }
        #endregion

        public Bitmask(string[] bitNames, int byteCountLength)
        {
            BitNames = bitNames;
            __length = byteCountLength;
            Bits = new bool[byteCountLength * 8];
        }

        public Bitmask(byte[] Bytes)
        {
            Bits = ConvertToBoolArray(Bytes);
            __length = Bytes.Length;
        }

        public void SetAllData(byte[] Bytes)
        {
            Bits = ConvertToBoolArray(Bytes);
            __length = Bytes.Length;
        }

        /// <summary>
        /// Converts An Array Of Bytes To An Array Bits As Booleans
        /// </summary>
        /// <param name="Bytes"></param>
        /// <returns></returns>
        public static bool[] ConvertToBoolArray(byte[] Bytes)
        {
            bool[] bitArray = new bool[Bytes.Length * 8];
            int input;
            int bittester;

            for (int i = 0; i < Bytes.Length; i++)
            {
                input = BitConverter.ToInt16(new byte[2] { Bytes[i], 0 }, 0);
                bittester = 1;

                for (int counter = 0; counter < 8; counter++)
                {
                    bitArray[(i * 8) + counter] = (input & bittester) > 0 ? true : false;
                    bittester *= 2;
                }
            }

            return bitArray;
        }

        public static byte[] ConvertToByteArray(Bitmask bitmask)
        {
            int BitData;
            BitData = 0;

            for (int z = 0; z < bitmask.Bits.Length; z++)
            {
                BitData = setBit(BitData, z, bitmask.Bits[z]);
            }

            byte[] AllBytes = BitConverter.GetBytes(BitData);
            byte[] ReturnBytes = new byte[bitmask.ByteCountLength];

            for (int i = 0; i < bitmask.ByteCountLength; i++)
            {
                ReturnBytes[i] = AllBytes[i];
            }

            return ReturnBytes;
        }

        private static int setBit(int integer, int bitIndex, bool onOff)
        {
            if (onOff == true)
            {
                integer = (1 << bitIndex) | integer;
            }
            else
            {
                integer = ~(1 << bitIndex) & integer;
            }
            return integer;
        }
    }
}
